package week1

import "fmt"

/*
实现删除切片特定下标元素的方法。
要求一：能够实现删除操作就可以。
要求二：考虑使用比较高性能的实现。
要求三：改造为泛型方法
要求四：支持缩容，并且设计缩容机制。
*/

// TSlice
//
//	arr 底层切片
//	length 长度标记
type TSlice[T any] struct {
	arr []T
}

// NewTSlice 构造函数
func NewTSlice[T any](elements ...T) *TSlice[T] {
	return &TSlice[T]{
		arr: elements,
	}
}

// Set 添加元素
// 将idx之后的所有元素依次向前移动一位
// 空出来的部分用零值替代
func (s *TSlice[T]) Set(idx int, element T) bool {
	if idx < 0 || idx > len(s.arr)-1 {
		return false
	}
	s.arr[idx] = element
	return true
}

// Append 在末尾追加元素
func (s *TSlice[T]) Append(element T) bool {
	s.arr = append(s.arr, element)
	return true
}

// Delete 删除下标为idx的元素
// 将idx之后的所有元素依次向前移动一位
// 空出来的部分用零值替代
func (s *TSlice[T]) Delete(idx int) bool {
	arrLen := len(s.arr)
	if idx < 0 || idx > arrLen-1 {
		return false
	}

	for i := idx; i+1 < arrLen-1; i++ {
		s.arr[i] = s.arr[i+1]
	}

	var zeroVal T
	s.arr[arrLen-1] = zeroVal
	s.arr = s.arr[:arrLen-1]

	return true
}

// Shrink 检测容量与空位和容量的比重
// 如果空位过多则触发切片收缩
// 收缩策略: 借鉴扩容的策略
//
//	a. 总容量<256 && 空余位置超过75%
//		则将切片容量收缩至 当前长度*2
//	b. 总容量>256 且 空余位置超过66%
//		从256开始 以1.25倍的速率逐步递增的
//		获取能容纳当前容量的元素的最小长度
func (s *TSlice[T]) Shrink() {
	arrCap := cap(s.arr)
	arrLen := len(s.arr)

	if cap(s.arr) < 256 && (arrCap-arrLen)*100/cap(s.arr) > 75 {
		arrCap = arrLen * 2
	}

	if cap(s.arr) > 256 && (arrCap-arrLen)*100/cap(s.arr) > 66 {
		arrCap = 256.0
		for {
			if arrCap > arrLen {
				break
			}
			arrCap = arrCap * 5 / 4
		}
	}
	if arrCap != cap(s.arr) {
		newArr := make([]T, arrLen, arrCap)
		copy(newArr, s.arr[:int(arrCap)])
		s.arr = newArr
	}
}

func (s *TSlice[T]) Print() {
	fmt.Printf("len:%d, cap:%d, arr: %v \n",
		len(s.arr), cap(s.arr), s.arr)
}
